﻿/**
 * @file std_stack.inl
 * Copyright (c) 2019 Gaaagaa. All rights reserved.
 * 
 * @author  : Gaaagaa
 * @date    : 2019-09-09
 * @version : 1.0.0.0
 * @brief   : 定义 栈容器 内部相关数据类型、常量、宏 等。
 */

/**
 * The MIT License (MIT)
 * Copyright (c) Gaaagaa. All rights reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef __STD_STACK_INL__
#define __STD_STACK_INL__

#ifndef __STD_STACK_H__
#error "Please include std_stack.h before this file."
#endif // __STD_QUEUE_H__

#include "std_comm.inl"

////////////////////////////////////////////////////////////////////////////////
// xstd_stack_t 的相关数据类型定义

/** 块对象缓存是否与 所存储的元素数组缓存 分离 */
#define XSTK_CHUNK_SEPARATED 0

/** 块对象指针 */
typedef struct xstk_chunk_t * xstk_cptr_t;

/**
 * @struct xstk_chunk_t
 * @brief  存储元素的内存块 结构体描述信息。
 */
typedef struct xstk_chunk_t
{
    xstk_cptr_t   xchk_next;    ///< 指向后继的块对象

#if XSTK_CHUNK_SEPARATED

    xstd_bptr_t   xchk_dptr;    ///< 块对象中所存储的元素数组缓存

#else // !XSTK_CHUNK_SEPARATED

#ifdef _MSC_VER
#pragma warning(disable:4200)
#endif // _MSC_VER
    xstd_byte_t   xchk_dptr[0]; ///< 块对象中所存储的元素数组缓存
#ifdef _MSC_VER
#pragma warning(default:4200)
#endif // _MSC_VER

#endif // XSTK_CHUNK_SEPARATED

} xstk_chunk_t;

/**
 * @struct xstd_stack_t
 * @brief  栈容器的结构体描述信息。
 */
typedef struct xstd_stack_t
{
    xstd_context_t  xstd_ectxt;  ///< 节点类型的上下文描述信息
    xstk_size_t     xchk_size;   ///< 元素存储分块的 节点容量（取值为 2^N ）
    xstk_size_t     xstk_size;   ///< 当前存储的元素节点数量

    /** 指向队列顶端的块存储信息 */
    struct
    {
    xstk_cptr_t     xchk_mptr;   ///< 内存块
    xstk_size_t     xchk_vpos;   ///< 当前存储节点的索引号
    } xstk_top;
} xstd_stack_t;

////////////////////////////////////////////////////////////////////////////////
// xstd_stack_t 的相关操作宏函数

//====================================================================

#define XSTK_ECTXT(xstk_this)   XSTD_ECTXT(xstk_this)
#define XSTK_ETYPE(xstk_this)   XSTD_ETYPE(xstk_this)
#define XSTK_ESIZE(xstk_this)   XSTD_ESIZE(xstk_this)
#define XSTK_ALTOR(xstk_this)   XSTD_ALTOR(xstk_this)

#define XSTK_MALLOC(xstk_this, xst_size)            \
            XSTD_MALLOC((xstk_this), (xst_size))

#define XSTK_DEALLOC(xstk_this, xmt_mptr)           \
            XSTD_DEALLOC((xstk_this), (xmt_mptr))

#define XSTK_ALFROM(xstk_this, xet_dptr, xet_sptr)  \
            XSTD_ALFROM((xstk_this), (xet_dptr), (xet_sptr))

#define XSTK_ALMOVE(xstk_this, xet_dptr, xet_sptr)  \
            XSTD_ALMOVE((xstk_this), (xet_dptr), (xet_sptr))

#define XSTK_ALDEST(xstk_this, xet_elem)            \
            XSTD_ALDEST((xstk_this), (xet_elem))

#define XSTK_ISSAME_TYPE(xstk_lthis, xstk_rthis)    \
            XSTD_ISSAME_TYPE((xstk_lthis), (xstk_rthis))

#define XSTK_ECTXT_UPDATE(xstk_this, xstk_ctxt)     \
            XSTD_ECTXT_UPDATE((xstk_this), (xstk_ctxt))

//====================================================================

#if XSTK_CHUNK_SEPARATED
#define XSTK_SIZEOF_CHUNK(xstk_this)  (sizeof(xstk_chunk_t))
#else // !XSTK_CHUNK_SEPARATED
#define XSTK_SIZEOF_CHUNK(xstk_this)  \
    (sizeof(xstk_chunk_t) + (xstk_this)->xchk_size * XSTK_ESIZE(xstk_this))
#endif // XSTK_CHUNK_SEPARATED

#define XSTK_MAX_SIZE(xstk_this) \
    ((xstk_size_t)(((xstk_size_t)~0) / XSTK_ESIZE(xstk_this)))

#define XSTK_TOP(xstk_this)                                         \
    ((xstk_elem_t)(                                                 \
        ((xstd_bptr_t)(xstk_this)->xstk_top.xchk_mptr->xchk_dptr) + \
        (XSTK_ESIZE(xstk_this) * (xstk_this)->xstk_top.xchk_vpos)))

//====================================================================

////////////////////////////////////////////////////////////////////////////////

#endif // __STD_STACK_INL__
